package com.gec.service.Impl;

import com.gec.dao.DeptDao;
import com.gec.dao.ProcessConfigDao;
import com.gec.dao.ReimDao;
import com.gec.domain.PageBean;
import com.gec.domain.PageParam;
import com.gec.domain.ProcessConfig;
import com.gec.domain.Reim;
import com.gec.service.abst.ReimService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/*
 *  Type: Interface
 *  Author: DawnFz.com
 *  Date: 2022/10/26 9:32
 *  Project: HotelSSM
 *  Version: 1.0
 *  Describe: [ReimServiceImpl接口]
 */
@Service
public class ReimServiceImpl extends BaseService implements ReimService
{

    private final ReimDao reimDao;
    private final DeptDao deptDao;
    private final ProcessConfigDao processConfigDao;
    private final RuntimeService runtimeService;

    private final HistoryService historyService;

    private final TaskService taskService;

    public ReimServiceImpl(ReimDao reimDao, DeptDao deptDao,
                           ProcessConfigDao processConfigDao,
                           RuntimeService runtimeService,
                           HistoryService historyService,
                           TaskService taskService)
    {
        this.reimDao = reimDao;
        this.deptDao = deptDao;
        this.processConfigDao = processConfigDao;
        this.runtimeService = runtimeService;
        this.historyService = historyService;
        this.taskService = taskService;
    }

    @Override
    public String getHigherDeptLeader(String deptId)
    {
        String higherDept = deptDao.findHigherLevelDept(deptId);
        return deptDao.findDeptLeaderId(higherDept);
    }

    @Override
    public String getHigherDeptBoss(String deptId)
    {
        String higherDept = deptDao.findHigherLevelDept(deptId);
        return deptDao.findDeptBossId(higherDept);
    }

    @Override
    public String getDeptLeader(String deptId)
    {
        return deptDao.findDeptLeaderId(deptId);
    }

    @Override
    public String getDeptBoss(String deptId)
    {
        return deptDao.findDeptBossId(deptId);
    }

    @Override
    public int updateAssigneeAndTask(String insId, String taskId, String assignee)
    {
        return reimDao.updateAssigneeAndTask(insId, taskId, assignee);
    }

    /*--------------------------------------------------*/
    private Map<String, Object> setVariables(Reim reim)
    {
        //[1] 创建一个 Map容器 用于存储流程变量
        Map<String, Object> data = new HashMap<>();
        //[2] 设置流程变量并返回该变量容器
        data.put("initiator", reim.getInitiator());
        data.put("title", reim.getTitle());
        data.put("money", reim.getPrice());
        data.put("reason", reim.getReason());
        data.put("isCancel", "false");

        return data;
    }

    @Override
    public void startProcess(Reim reim)
    {
        //[1] 查询最新版本的请假流程定义Id
        ProcessConfig config = processConfigDao.getProcessByCategory("报销流程");
        String procDefId = config.getProcDefId();
        //[3] 设置并获取流程变量
        Map<String, Object> processData = setVariables(reim);
        //[4] 传入流程变量并开启流程实例
        ProcessInstance instance = runtimeService.startProcessInstanceById(procDefId, processData);
        //[5] 从流程实例获取数据设置到Leave对象中
        String instanceId = instance.getId();
        reim.setProcInstId(instanceId);
        reim.setProcDefId(instance.getProcessDefinitionId());
        reim.setStatus("办理中");
        //[6] 写入Leave对象到 t_leave 表
        int i = reimDao.addReim(reim);
        System.out.println("[ " + i + " 条数据已先写入数据库 ]");
        //[7] 提交Andy的请假任务
        commitReim(reim.getInitiator(), instanceId);
    }

    private void commitReim(String initiator, String instanceId)
    {
        //[1] 根据 办理人(initiator) 和流程实例 Id(instanceId) 查询该任务
        Task task = taskService.createTaskQuery()
                .taskAssignee(initiator)
                .processInstanceId(instanceId)
                .singleResult();
        //[2] 根据该任务Id提交本次任务记录进入下一个流程
        taskService.complete(task.getId());
    }

    /*--------------------------------------------------*/

    @Override
    public PageBean<Reim> queryInitiate(PageParam param, String initiator)
    {
        //[1] 获取 页码 与 页大小
        int _page = param.getPage();
        int _limit = param.getLimit();
        //[2] 使用分页插件开启分页查询
        Page<Object> pageObjs = PageHelper.startPage(_page, _limit, true);
        //[3] 查询我发起的请假 (t_reim表)
        List<Reim> reimS = reimDao.queryInitiate(initiator);
        //[4] 获取查询的总记录数
        int count = (int) pageObjs.getTotal();
        PageBean<Reim> pageBean = new PageBean<>();
        //[5] 设置数据到PageBean封装对象中
        pageBean.setCount(count);
        pageBean.setData(reimS);
        pageBean.setCode(0);
        //[6] 返回封装好的PageBean
        return pageBean;
    }

    /*--------------------------------------------------*/
    @Override
    public PageBean<Reim> queryWaitMyApprove(PageParam param, String assigneeId)
    {
        //[1] 获取 页码 与 页大小
        int _page = param.getPage();
        int _limit = param.getLimit();
        //[2] 使用分页插件开启分页查询
        Page<Object> pageObjs = PageHelper.startPage(_page, _limit, true);
        //[3] 查询待我审批的任务 (t_leave表)
        List<Reim> reimS = reimDao.queryWaitMyApprove(assigneeId);
        //[4] 获取查询的总记录数
        int count = (int) pageObjs.getTotal();
        PageBean<Reim> pageBean = new PageBean<>();
        //[5] 设置数据到PageBean封装对象中
        pageBean.setCount(count);
        pageBean.setData(reimS);
        pageBean.setCode(0);
        //[6] 返回封装好的PageBean
        return pageBean;
    }

    /*--------------------------------------------------*/
    @Override
    public PageBean<Reim> queryMyApproved(PageParam param, String assigneeId)
    {
        //[1] 获取 页码 与 页大小
        int _page = param.getPage();
        int _limit = param.getLimit();
        //[2] 使用分页插件开启分页查询
        Page<Object> pageObjs = PageHelper.startPage(_page, _limit, true);
        //[3] 查询待我审批的任务 (t_leave表)
        List<Reim> reimS = reimDao.queryMyApproved(assigneeId);
        //[4] 获取查询的总记录数
        int count = (int) pageObjs.getTotal();
        PageBean<Reim> pageBean = new PageBean<>();
        //[5] 设置数据到PageBean封装对象中
        pageBean.setCount(count);
        pageBean.setData(reimS);
        pageBean.setCode(0);
        //[6] 返回封装好的PageBean
        return pageBean;
    }

    @Override
    public Reim queryMyTaskByTaskId(String taskId)
    {
        Reim reim = reimDao.queryMyTaskByTaskId(taskId);
        if (reim == null) throw new RuntimeException("找不到该报销记录");
        return reim;
    }

    @Override
    public void updateStatusByInstance(String processInstanceId, String status)
    {
        int i = reimDao.updateStatusByInstance(processInstanceId, status);
        if (i != 1) throw new RuntimeException("更新状态失败。");
    }

    @Override
    public void clearTaskAndAssignee(String processInstanceId)
    {
        int i = reimDao.clearTaskAndAssignee(processInstanceId);
        if (i != 1) throw new RuntimeException("清空任务和办理人失败。");
    }

    @Override
    public void completeMyApprove(Map<String, Object> map)
    {
        String deptId = (String) map.get("deptId");
        String appFlag = (String) map.get("appFlag");
        String taskId = (String) map.get("taskId");
        //根据 部门Id 查询更高一级 部门Id
        String higherDeptId = deptDao.findHigherLevelDept(deptId);
        map.put("appRet", appFlag);

        //把办理人置空
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String processInstanceId = task.getProcessInstanceId();

        //加入到我已审批列表
        addRecordToHistoricReim(processInstanceId, task.getAssignee());

        if (!Boolean.parseBoolean(appFlag)) reimDao.updateStatusByInstance(processInstanceId, "已拒绝");
        reimDao.updateAssigneeAndTask(processInstanceId, null, null);

        //提交当前任务
        taskService.complete(taskId, map);
    }

    // 自行取消申请
    @Override
    public void cancelMyTaskByProcessInstanceId(String instanceId)
    {
        Task task = taskService.createTaskQuery()
                .processInstanceId(instanceId)
                .singleResult();
        Map<String, Object> data = new HashMap<>();
        data.put("isCancel", "true");
        String taskId = task.getId();
        taskService.complete(taskId, data);
    }

    @Override
    public PageBean<Reim> queryHistoryApproved(PageParam param, String assignee)
    {
        //[0] 查询并且制造 processInstanceIds
        List<String> processInstanceIdList = reimDao.queryHistoricProcessInstanceIdByAssignee(assignee);
        if (processInstanceIdList.size() == 0) return new PageBean<>();
        StringBuilder processInstanceIds = new StringBuilder();
        Iterator<String> iterator = processInstanceIdList.iterator();
        while (iterator.hasNext())
        {
            processInstanceIds.append(iterator.next());
            if (iterator.hasNext()) processInstanceIds.append(", ");
        }
        //[1] 获取 页码 与 页大小
        int _page = param.getPage();
        int _limit = param.getLimit();
        //[2] 使用分页插件开启分页查询
        Page<Object> pageObjs = PageHelper.startPage(_page, _limit, true);
        List<Reim> reimS = reimDao.queryMyApprovedByProcessInstanceIds(processInstanceIds.toString());
        int count = (int) pageObjs.getTotal();
        PageBean<Reim> pageBean = new PageBean<>();
        //[5] 设置数据到PageBean封装对象中
        pageBean.setCount(count);
        pageBean.setData(reimS);
        pageBean.setCode(0);
        //[6] 返回封装好的PageBean
        return pageBean;
    }

    //添加到历史记录
    @Override
    public int addRecordToHistoricReim(String processInstanceId, String assignee)
    {
        return reimDao.addRecordToHistoricReim(processInstanceId, assignee);
    }

    @Override
    public String getUserIdByDeptId(String deptId)
    {
        return deptDao.getUserIdByDeptId(deptId);
    }

}
